{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: 'G:\\\\two\\\\students.xlsx'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[1], line 27\u001b[0m\n\u001b[0;32m     25\u001b[0m \u001b[38;5;66;03m# 加载数据集\u001b[39;00m\n\u001b[0;32m     26\u001b[0m file_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mG:\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mtwo\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mstudents.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m---> 27\u001b[0m data \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread_excel\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     29\u001b[0m \u001b[38;5;66;03m# 设置 Pandas 的显示选项\u001b[39;00m\n\u001b[0;32m     30\u001b[0m pd\u001b[38;5;241m.\u001b[39mset_option(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdisplay.max_rows\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)  \u001b[38;5;66;03m# 显示所有行\u001b[39;00m\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python39\\site-packages\\pandas\\io\\excel\\_base.py:495\u001b[0m, in \u001b[0;36mread_excel\u001b[1;34m(io, sheet_name, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, date_format, thousands, decimal, comment, skipfooter, storage_options, dtype_backend, engine_kwargs)\u001b[0m\n\u001b[0;32m    493\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(io, ExcelFile):\n\u001b[0;32m    494\u001b[0m     should_close \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 495\u001b[0m     io \u001b[38;5;241m=\u001b[39m \u001b[43mExcelFile\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    496\u001b[0m \u001b[43m        \u001b[49m\u001b[43mio\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    497\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    498\u001b[0m \u001b[43m        \u001b[49m\u001b[43mengine\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mengine\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    499\u001b[0m \u001b[43m        \u001b[49m\u001b[43mengine_kwargs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mengine_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    500\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    501\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;129;01mand\u001b[39;00m engine \u001b[38;5;241m!=\u001b[39m io\u001b[38;5;241m.\u001b[39mengine:\n\u001b[0;32m    502\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m    503\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEngine should not be specified when passing \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    504\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man ExcelFile - ExcelFile already has the engine set\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    505\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python39\\site-packages\\pandas\\io\\excel\\_base.py:1550\u001b[0m, in \u001b[0;36mExcelFile.__init__\u001b[1;34m(self, path_or_buffer, engine, storage_options, engine_kwargs)\u001b[0m\n\u001b[0;32m   1548\u001b[0m     ext \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxls\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1549\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1550\u001b[0m     ext \u001b[38;5;241m=\u001b[39m \u001b[43minspect_excel_format\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1551\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\n\u001b[0;32m   1552\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   1553\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m ext \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m   1554\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m   1555\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExcel file format cannot be determined, you must specify \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1556\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man engine manually.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1557\u001b[0m         )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python39\\site-packages\\pandas\\io\\excel\\_base.py:1402\u001b[0m, in \u001b[0;36minspect_excel_format\u001b[1;34m(content_or_path, storage_options)\u001b[0m\n\u001b[0;32m   1399\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(content_or_path, \u001b[38;5;28mbytes\u001b[39m):\n\u001b[0;32m   1400\u001b[0m     content_or_path \u001b[38;5;241m=\u001b[39m BytesIO(content_or_path)\n\u001b[1;32m-> 1402\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1403\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mis_text\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\n\u001b[0;32m   1404\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handle:\n\u001b[0;32m   1405\u001b[0m     stream \u001b[38;5;241m=\u001b[39m handle\u001b[38;5;241m.\u001b[39mhandle\n\u001b[0;32m   1406\u001b[0m     stream\u001b[38;5;241m.\u001b[39mseek(\u001b[38;5;241m0\u001b[39m)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python39\\site-packages\\pandas\\io\\common.py:882\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m    873\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m    874\u001b[0m             handle,\n\u001b[0;32m    875\u001b[0m             ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    878\u001b[0m             newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    879\u001b[0m         )\n\u001b[0;32m    880\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    881\u001b[0m         \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[1;32m--> 882\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mioargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    883\u001b[0m     handles\u001b[38;5;241m.\u001b[39mappend(handle)\n\u001b[0;32m    885\u001b[0m \u001b[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001b[39;00m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'G:\\\\two\\\\students.xlsx'"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.font_manager as fm\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense\n",
    "from sklearn.metrics import classification_report, confusion_matrix\n",
    "from sklearn.ensemble import IsolationForest\n",
    "import numpy as np\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.naive_bayes import GaussianNB\n",
    "from tensorflow.keras.optimizers import Adam\n",
    "from tensorflow.keras.callbacks import LearningRateScheduler\n",
    "from xgboost import XGBClassifier\n",
    "from xgboost import XGBRegressor\n",
    "\n",
    "# 加载本地字体并设置为全局字体\n",
    "font_path = r'c:\\windows\\fonts\\STZHONGS.TTF'\n",
    "my_font = fm.FontProperties(fname=font_path)\n",
    "plt.rcParams['font.family'] = my_font.get_name()\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 加载数据集\n",
    "file_path = 'students.xlsx'\n",
    "data = pd.read_excel(file_path)\n",
    "\n",
    "# 设置 Pandas 的显示选项\n",
    "pd.set_option('display.max_rows', None)  # 显示所有行\n",
    "pd.set_option('display.max_columns', None)  # 显示所有列\n",
    "pd.set_option('display.width', None)  # 自动调整宽度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据的初步概览和可视化展示\n",
    "print(\"数据集的前几行：\\n\", data.head())\n",
    "print(\"数据集的描述性统计：\\n\", data.describe())\n",
    "print(\"数据集的列名：\\n\", data.columns)\n",
    "\n",
    "# 检查缺失值\n",
    "print(\"缺失值统计：\\n\", data.isnull().sum())\n",
    "\n",
    "# 可视化缺失值\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.heatmap(data.isnull(), cbar=False, cmap='viridis')\n",
    "plt.title('缺失值热图', fontproperties=my_font)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 编码分类特征并存储到新数据框\n",
    "encoded_data = data.copy()\n",
    "label_encoders = {}\n",
    "for column in encoded_data.select_dtypes(include=['object']).columns:\n",
    "    le = LabelEncoder()\n",
    "    encoded_data[column] = le.fit_transform(encoded_data[column])\n",
    "    label_encoders[column] = le\n",
    "\n",
    "# 使用 Isolation Forest 检测离群点\n",
    "model = IsolationForest(contamination=0.05, random_state=42)\n",
    "\n",
    "# 仅选择数值特征进行离群点检测\n",
    "numerical_data = encoded_data.select_dtypes(include=[np.number])\n",
    "if numerical_data.empty:\n",
    "    print(\"数值数据为空，请检查数据格式或内容！\")\n",
    "else:\n",
    "    # 正确使用fit_predict方法\n",
    "    encoded_data['outlier'] = model.fit_predict(numerical_data.values)\n",
    "\n",
    "    # 提取离群点\n",
    "    outliers = encoded_data[encoded_data['outlier'] == -1]\n",
    "\n",
    "    # 输出离群点\n",
    "    print(f\"检测到的离群点（编码后）：\\n{outliers}\\n\")\n",
    "\n",
    "    # 删除离群点\n",
    "    cleaned_encoded_data = encoded_data[encoded_data['outlier']!= -1]\n",
    "    print(\"删除离群点后的编码数据集大小：\", cleaned_encoded_data.shape)\n",
    "\n",
    "    # 通过索引在原始数据中删除离群点\n",
    "    outlier_indices = outliers.index\n",
    "    cleaned_data = data.drop(index=outlier_indices)\n",
    "\n",
    "    # 输出原始数据中的离群点\n",
    "    original_outliers = data.loc[outlier_indices]\n",
    "    print(f\"原始数据中的离群点：\\n{original_outliers}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 假设标签列名为 '申请助学贷款情况'\n",
    "label = '申请助学贷款情况'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对每个非数值列进行编码，并保存映射关系（这里重新编码，确保数据格式符合后续模型要求）\n",
    "label_mappings = {}\n",
    "for column in cleaned_data.select_dtypes(include=['object']).columns:\n",
    "    le = LabelEncoder()\n",
    "    cleaned_data[column] = le.fit_transform(cleaned_data[column])\n",
    "    label_mappings[column] = dict(zip(le.classes_, le.transform(le.classes_)))\n",
    "\n",
    "# 打印每个列的编码映射\n",
    "for col, mapping in label_mappings.items():\n",
    "    print(f\"列 '{col}' 的整数编码映射：\")\n",
    "    for original, encoded in mapping.items():\n",
    "        print(f\"  {original} -> {encoded}\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算相关系数矩阵\n",
    "correlation_matrix = cleaned_data.corr()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取与标签的相关系数\n",
    "label_correlation = correlation_matrix[label].drop(label)  # 去掉标签自身的相关系数\n",
    "label_correlation_sorted = label_correlation.abs().sort_values(ascending=False)\n",
    "\n",
    "# 选择与标签相关系数最高的 5个特征\n",
    "top_features = label_correlation_sorted.head(5).index.tolist()\n",
    "\n",
    "# 可视化整个相关系数矩阵，并标出前5个特征\n",
    "plt.figure(figsize=(12, 10))\n",
    "sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', cbar_kws={'label': '相关系数'})\n",
    "plt.xticks(rotation=45, ha='right') \n",
    "plt.title('相关系数矩阵（前5个与标签相关的特征已标记）', fontproperties=my_font)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 高亮显示前5个与标签相关的特征\n",
    "for feature in top_features:\n",
    "    plt.gca().add_patch(plt.Rectangle((correlation_matrix.columns.get_loc(feature), \n",
    "                                       correlation_matrix.index.get_loc(label)),\n",
    "                                      1, 1, fill=False, edgecolor='yellow', lw=3))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用前5个特征作为模型输入\n",
    "X = cleaned_data[top_features]\n",
    "y = cleaned_data[label]\n",
    "\n",
    "# 划分训练集和测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# 标准化特征\n",
    "scaler = StandardScaler()\n",
    "X_train_scaled = scaler.fit_transform(X_train)\n",
    "X_test_scaled = scaler.transform(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建简单的神经网络模型\n",
    "neural_network_model = Sequential([\n",
    "    Dense(16, activation='elu', input_shape=(X_train_scaled.shape[1],)),\n",
    "    Dense(8, activation='relu'),\n",
    "    Dense(1, activation='sigmoid')\n",
    "])\n",
    "\n",
    "# 编译神经网络模型\n",
    "optimizer = Adam(0.0001)\n",
    "neural_network_model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])\n",
    "\n",
    "# 定义学习率调度函数（用于神经网络模型训练）\n",
    "def scheduler(epoch, lr):\n",
    "    if epoch > 10:  # 在第10个epoch之后降低学习率\n",
    "        return lr * 0.9  # 每个epoch将学习率减少10%\n",
    "    return lr\n",
    "\n",
    "# 实例化神经网络模型的学习率调度器\n",
    "lr_scheduler = LearningRateScheduler(scheduler)\n",
    "\n",
    "# 训练神经网络模型，添加学习率调度器\n",
    "neural_network_history = neural_network_model.fit(X_train_scaled, y_train, epochs=100, batch_size=12, validation_split=0.2, callbacks=[lr_scheduler])\n",
    "\n",
    "# 可视化神经网络模型训练过程中的损失和准确率\n",
    "plt.figure(figsize=(12, 6))\n",
    "\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.plot(neural_network_history.history['loss'], label='神经网络训练集损失')\n",
    "plt.plot(neural_network_history.history['val_loss'], label='神经网络验证集损失')\n",
    "plt.title('神经网络训练过程中的损失', fontproperties=my_font)\n",
    "plt.xlabel('Epoch', fontproperties=my_font)\n",
    "plt.ylabel('Loss', fontproperties=my_font)\n",
    "plt.legend(prop=my_font)\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(neural_network_history.history['accuracy'], label='神经网络训练集准确率')\n",
    "plt.plot(neural_network_history.history['val_accuracy'], label='神经网络验证集准确率')\n",
    "plt.title('神经网络训练过程中的准确率', fontproperties=my_font)\n",
    "plt.xlabel('Epoch', fontproperties=my_font)\n",
    "plt.ylabel('Accuracy', fontproperties=my_font)\n",
    "plt.legend(prop=my_font)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建支持向量机模型\n",
    "svm_model = SVC(kernel='rbf', probability=True)\n",
    "\n",
    "# 训练支持向量机模型\n",
    "svm_model.fit(X_train_scaled, y_train)\n",
    "\n",
    "# 构建朴素贝叶斯模型\n",
    "naive_bayes_model = GaussianNB()\n",
    "\n",
    "# 训练朴素贝叶斯模型\n",
    "naive_bayes_model.fit(X_train_scaled, y_train)\n",
    "\n",
    "# 构建xgb模型\n",
    "xgb_classifier_model = XGBClassifier(use_label_encoder=False, eval_metric='logloss')\n",
    "\n",
    "# 训练 XGBoost 分类器模型\n",
    "xgb_classifier_model.fit(X_train_scaled, y_train)\n",
    "\n",
    "# 在测试集上评估神经网络模型\n",
    "neural_network_y_pred = neural_network_model.predict(X_test_scaled).round().astype(int)\n",
    "\n",
    "# 在测试集上评估支持向量机模型\n",
    "svm_y_pred = svm_model.predict(X_test_scaled)\n",
    "\n",
    "# 在测试集上评估朴素贝叶斯模型\n",
    "naive_bayes_y_pred = naive_bayes_model.predict(X_test_scaled)\n",
    "\n",
    "# 在测试集上评估 XGBoost 分类器\n",
    "xgb_y_pred = xgb_classifier_model.predict(X_test_scaled)\n",
    "\n",
    "# 确保在使用label_mapping之前定义它\n",
    "label_mapping = {0: '没有申请过', 1: '申请并获得', 2: '申请未获得'}\n",
    "\n",
    "# 将神经网络模型预测值和实际值映射为中文标签\n",
    "neural_network_y_test_mapped = pd.Series(y_test).map(label_mapping)\n",
    "neural_network_y_pred_mapped = pd.Series(neural_network_y_pred.flatten()).map(label_mapping)\n",
    "\n",
    "# 将支持向量机模型预测值和实际值映射为中文标签\n",
    "svm_y_test_mapped = pd.Series(y_test).map(label_mapping)\n",
    "svm_y_pred_mapped = pd.Series(svm_y_pred).map(label_mapping)\n",
    "\n",
    "# 将朴素贝叶斯模型预测值和实际值映射为中文标签\n",
    "naive_bayes_y_test_mapped = pd.Series(y_test).map(label_mapping)\n",
    "naive_bayes_y_pred_mapped = pd.Series(naive_bayes_y_pred).map(label_mapping)\n",
    "\n",
    "# 将 XGBoost 分类器预测值和实际值映射为中文标签\n",
    "xgb_y_test_mapped = pd.Series(y_test).map(label_mapping)\n",
    "xgb_y_pred_mapped = pd.Series(xgb_y_pred).map(label_mapping)\n",
    "\n",
    "\n",
    "# 生成神经网络模型分类报告\n",
    "neural_network_report = classification_report(neural_network_y_test_mapped, neural_network_y_pred_mapped, output_dict=True, zero_division=1)\n",
    "\n",
    "# 生成支持向量机模型分类报告\n",
    "svm_report = classification_report(svm_y_test_mapped, svm_y_pred_mapped, output_dict=True, zero_division=1)\n",
    "\n",
    "# 生成朴素贝叶斯模型分类报告\n",
    "naive_bayes_report = classification_report(naive_bayes_y_test_mapped, naive_bayes_y_pred_mapped, output_dict=True, zero_division=1)\n",
    "\n",
    "# 生成 XGBoost 分类器分类报告\n",
    "xgb_classifier_report = classification_report(xgb_y_test_mapped, xgb_y_pred_mapped, output_dict=True, zero_division=1)\n",
    "\n",
    "\n",
    "# 可视化神经网络模型分类报告\n",
    "neural_network_df_report = pd.DataFrame(neural_network_report).transpose()\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.heatmap(neural_network_df_report.iloc[:-1, :].T, annot=True, cmap='coolwarm')\n",
    "plt.title('神经网络分类报告', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 可视化支持向量机模型分类报告\n",
    "svm_df_report = pd.DataFrame(svm_report).transpose()\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.heatmap(svm_df_report.iloc[:-1, :].T, annot=True, cmap='coolwarm')\n",
    "plt.title('支持向量机分类报告', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 可视化朴素贝叶斯模型分类报告\n",
    "naive_bayes_df_report = pd.DataFrame(naive_bayes_report).transpose()\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.heatmap(naive_bayes_df_report.iloc[:-1, :].T, annot=True, cmap='coolwarm')\n",
    "plt.title('朴素贝叶斯分类报告', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 可视化 XGBoost 分类器分类报告\n",
    "xgb_classifier_df_report = pd.DataFrame(xgb_classifier_report).transpose()\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.heatmap(xgb_classifier_df_report.iloc[:-1, :].T, annot=True, cmap='coolwarm')\n",
    "plt.title('XGBoost 分类器分类报告', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "\n",
    "# 绘制神经网络模型混淆矩阵\n",
    "neural_network_conf_matrix = confusion_matrix(neural_network_y_test_mapped, neural_network_y_pred_mapped, labels=['没有申请过', '申请并获得', '申请未获得'])\n",
    "plt.figure(figsize=(8, 6))\n",
    "sns.heatmap(neural_network_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('神经网络混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 绘制支持向量机模型混淆矩阵\n",
    "svm_conf_matrix = confusion_matrix(svm_y_test_mapped, svm_y_pred_mapped, labels=['没有申请过', '申请并获得', '申请未获得'])\n",
    "plt.figure(figsize=(8, 6))\n",
    "sns.heatmap(svm_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('支持向量机混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 绘制朴素贝叶斯模型混淆矩阵\n",
    "naive_bayes_conf_matrix = confusion_matrix(naive_bayes_y_test_mapped, naive_bayes_y_pred_mapped, labels=['没有申请过', '申请并获得', '申请未获得'])\n",
    "plt.figure(figsize=(8, 6))\n",
    "sns.heatmap(naive_bayes_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('朴素贝叶斯混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 绘制 XGBoost 分类器混淆矩阵\n",
    "xgb_classifier_conf_matrix = confusion_matrix(xgb_y_test_mapped, xgb_y_pred_mapped, labels=['没有申请过', '申请并获得', '申请未获得'])\n",
    "plt.figure(figsize=(8, 6))\n",
    "sns.heatmap(xgb_classifier_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('XGBoost 分类器混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 对比四个模型的性能\n",
    "\n",
    "# 将四个模型的分类报告合并到一个数据框中\n",
    "df_report_combined = pd.concat([neural_network_df_report, svm_df_report, naive_bayes_df_report, xgb_classifier_df_report], axis=1, keys=['神经网络', '支持向量机', '朴素贝叶斯'])\n",
    "\n",
    "# 可视化对比分类报告\n",
    "plt.figure(figsize=(14, 8))\n",
    "sns.heatmap(df_report_combined.iloc[:-1, :].T, annot=True, cmap='coolwarm')\n",
    "plt.title('神经网络、支持向量机与朴素贝叶斯分类报告对比', fontproperties=my_font)\n",
    "plt.show()\n",
    "\n",
    "# 绘制对比混淆矩阵\n",
    "plt.figure(figsize=(14, 6))\n",
    "\n",
    "plt.subplot(1, 3, 1)\n",
    "sns.heatmap(neural_network_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('神经网络混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "\n",
    "plt.subplot(1, 3, 2)\n",
    "sns.heatmap(svm_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('支持向量机混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "\n",
    "plt.subplot(1, 3, 3)\n",
    "sns.heatmap(naive_bayes_conf_matrix, annot=True, fmt=\"d\", cmap='coolwarm', xticklabels=label_mapping.values(), yticklabels=label_mapping.values())\n",
    "plt.title('朴素贝叶斯混淆矩阵', fontproperties=my_font)\n",
    "plt.xlabel('预测值', fontproperties=my_font)\n",
    "plt.ylabel('真实值', fontproperties=my_font)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9 (py39)",
   "language": "python",
   "name": "py39"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
